using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using NodeCanvas.Variables;
using UnityEngine;

namespace NodeCanvas.Actions
{
	[Category("✫ Script Control")]
	[Description("Execute a function on a script, of up to 3 parameters and save the return if any. If function is an IEnumerator it will start a coroutine and the action will run for as long as the coroutine is running. If the action stops, so will the coroutine.")]
	[AgentType(typeof(Transform))]
	public class ExecuteFunction : ActionTask
	{
		public BBVariableSet paramValue1 = new BBVariableSet();

		public BBVariableSet paramValue2 = new BBVariableSet();

		public BBVariableSet paramValue3 = new BBVariableSet();

		public BBVariableSet returnValue = new BBVariableSet
		{
			blackboardOnly = true
		};

		[SerializeField]
		private string methodName;

		[SerializeField]
		private string scriptName;

		private Component script;

		private MethodInfo method;

		private int paramCount;

		private bool routineRunning;

		protected override string info
		{
			get
			{
				if (string.IsNullOrEmpty(methodName))
				{
					return "No Method Selected";
				}
				string empty = string.Empty;
				empty += ((paramValue1.selectedType == null) ? string.Empty : paramValue1.selectedBBVariable.ToString());
				empty += ((paramValue2.selectedType == null) ? string.Empty : (", " + paramValue2.selectedBBVariable.ToString()));
				empty += ((paramValue3.selectedType == null) ? string.Empty : (", " + paramValue3.selectedBBVariable.ToString()));
				return ((returnValue.selectedType == null || returnValue.selectedBBVariable.isNone) ? string.Empty : (returnValue.selectedBBVariable.ToString() + "= ")) + base.agentInfo + "." + methodName + "(" + empty + ")";
			}
		}

		protected override string OnInit()
		{
			script = base.agent.GetComponent(scriptName);
			if (script == null)
			{
				return "Missing Component '" + scriptName + "' on Agent '" + base.agent.gameObject.name + "'";
			}
			List<Type> list = new List<Type>();
			if (paramValue1.selectedType != null)
			{
				list.Add(paramValue1.selectedType);
				if (paramValue2.selectedType != null)
				{
					list.Add(paramValue2.selectedType);
					if (paramValue3.selectedType != null)
					{
						list.Add(paramValue3.selectedType);
					}
				}
			}
			paramCount = list.Count;
			method = script.GetType().NCGetMethod(methodName, list.ToArray());
			if (method == null)
			{
				return "Method not found";
			}
			return null;
		}

		protected override void OnExecute()
		{
			object[] parameters = null;
			if (paramCount > 0)
			{
				if (paramCount == 1)
				{
					parameters = new object[1] { paramValue1.objectValue };
				}
				else if (paramCount == 2)
				{
					parameters = new object[2] { paramValue1.objectValue, paramValue2.objectValue };
				}
				else if (paramCount == 3)
				{
					parameters = new object[3] { paramValue1.objectValue, paramValue2.objectValue, paramValue3.objectValue };
				}
			}
			if (method.ReturnType == typeof(IEnumerator))
			{
				routineRunning = true;
				StartCoroutine(InternalCoroutine((IEnumerator)method.Invoke(script, parameters)));
			}
			else
			{
				returnValue.objectValue = method.Invoke(script, parameters);
				EndAction(true);
			}
		}

		protected override void OnStop()
		{
			routineRunning = false;
		}

		private IEnumerator InternalCoroutine(IEnumerator routine)
		{
			while (routine.MoveNext())
			{
				yield return routine.Current;
				if (!routineRunning)
				{
					yield break;
				}
			}
			EndAction(true);
		}
	}
}
